package com.apes.scm.settle.settle.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.repository.CooperationRepository;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.invoice.model.InvoiceItem;
import com.apes.scm.invoice.repository.InvoiceItemRepository;
import com.apes.scm.invoice.service.InvoiceService;
import com.apes.scm.masterdata.finance.model.BankAccount;
import com.apes.scm.masterdata.finance.repository.BankAccountRepository;
import com.apes.scm.masterdata.finance.repository.PaymentMethodRepository;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.settle.settle.model.*;
import com.apes.scm.settle.settle.respository.SettleRepository;
import com.apes.scm.settle.settle.respository.SettleSimpleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

import static com.apes.framework.util.DateUtil.SHOW_DATETIME_FORMAT;

@Service("settleSimpleService")
public class SettleSimpleService extends DomainService {
    @Autowired
    private SettleSimpleRepository settleSimpleRepository;

    @Autowired
    private InvoiceService invoiceService;

    @Autowired
    private LedgerService ledgerService;

    @Autowired
    private SettleSimpleDao settleSimpleDao;

    @Autowired
    private PartyRoleRepository partyRoleRepository;

    @Autowired
    private InvoiceItemRepository invoiceItemRepository;

    @Autowired
    private SettleService settleService;

    @Autowired
    private SettleRepository settleRepository;

    /**
     * 创建
     *
     * @param simpleRequest
     * @return
     */
    public SettleSimple create(SimpleRequest simpleRequest) {
        SettleSimple settleSimple = simpleRequest.getO(SettleSimple.class);

        settleSimple.setState("sent");//结算状态
        settleSimple.setInvoiceState("pending");//开票状态

        //筛选已勾选数据
        Set<SettleSimpleItem> settleSimpleItems = new HashSet<>();
        settleSimple.getSettleSimpleItems().forEach(v -> {
            if (v.getSelected() && v.getAmount() != 0) {
                if (!StringUtils.isEmpty(v.getNote()) && v.getNote().length() > 30)
                    throw new RuntimeException("回收备注数量不能大于30，请修改!");
                settleSimpleItems.add(v);
            }
        });

        if (settleSimpleItems.size() <= 0) throw new RuntimeException("请选择结算明细！");

        settleSimple.setSettleSimpleItems(settleSimpleItems);//付款方式明细
        settleSimple.setDept(SpringManager.getBean(DeptRepository.class).findByPartyRoleAndDeptType(settleSimple.getCompany().getId(), "000007"));//部门
        settleSimple = settleSimpleRepository.saveAndFlush(settleSimple);
        processSettleItems(settleSimple);//回写账单冻结金额
        extracted(settleSimple, "create");//写总账 账款:未清项
        return settleSimple;
    }

    private void processSettleItems(SettleSimple settleSimple) {
        Set<SettleSimpleItem> settleItems = settleSimple.getSettleSimpleItems();
        settleItems.forEach((item) -> {
                    // 增加结算表冻结数量
                    invoiceService.addInvoiceItemFreezeQty(item.getInvoiceItem(), item.getActualQty());
                }
        );
    }

    private void deleteSettleItems(SettleSimple settleSimple) {
        Set<SettleSimpleItem> settleItems = settleSimple.getSettleSimpleItems();
        settleItems.forEach((item) -> {
                    // 增加结算表冻结数量
                    invoiceService.decreaseInvoiceItemFreezeQty(item.getInvoiceItem(), item.getActualQty() * -1);
                }
        );
    }

    private void savaSettleItems(SettleSimple settleSimple) {
        Set<SettleSimpleItem> settleItems = settleSimple.getSettleSimpleItems();
        settleItems.forEach((item) -> {
                    // 增加完成数量
                    invoiceService.addInvoiceItemSettledQty(item.getInvoiceItem(), item.getActualQty());
                    // 减少冻结数量
                    invoiceService.decreaseInvoiceItemFreezeQty(item.getInvoiceItem(), item.getActualQty() * -1);
                }
        );
    }

    private void updateSettleItems(SettleSimple settleSimple) {
        SettleSimple simple = settleSimpleRepository.getOne(settleSimple.getId());
        Set<SettleSimpleItem> settleItems = simple.getSettleSimpleItems();
        settleItems.forEach((item) -> {
                    // 增加冻结数
                    invoiceService.decreaseInvoiceItemFreezeQty(item.getInvoiceItem(), item.getActualQty() * -1);
                }
        );
    }

    /**
     * 编辑
     *
     * @param simpleRequest
     * @return
     */
    public SettleSimple update(SimpleRequest simpleRequest) {
        SettleSimple settleSimple = simpleRequest.getO(SettleSimple.class);
        Set<SettleSimpleItem> settleSimpleItems = new HashSet<>();

        //筛选已勾选数据
        settleSimple.getSettleSimpleItems().forEach(v -> {
            if (v.getSelected() && v.getAmount() != 0) {
                if (!StringUtils.isEmpty(v.getNote()) && v.getNote().length() > 30)
                    throw new RuntimeException("回收备注数量不能大于30，请修改!");
                settleSimpleItems.add(v);
            }
        });
        settleSimple.setSettleSimpleItems(settleSimpleItems);
        updateSettleItems(settleSimple);//未勾选，减冻结
        processSettleItems(settleSimple);//减冻结，加已扣

        extracted(settleSimpleRepository.getOne(settleSimple.getId()), "delete");//还原总账
        extracted(settleSimple, "create");//重写总账

        if (settleSimpleItems.size() < 1) throw new RuntimeException("请选择结算明细！");
        return settleSimpleRepository.saveAndFlush(settleSimple);
    }


    /**
     * 审核
     *
     * @param simpleRequest
     * @return
     */
    public SettleSimple approve(SimpleRequest simpleRequest) {
        SettleSimple settleSimple = simpleRequest.getO(SettleSimple.class);
        //筛选已勾选数据
        settleSimple.getSettleSimpleItems().forEach(v -> {
            if (!StringUtils.isEmpty(v.getNote()) && v.getNote().length() > 30)
                throw new RuntimeException("回收备注数量不能大于30，请修改!");
        });

        if (settleSimple.getPaymentMethodSet().size() <= 0) throw new RuntimeException("请选择收款方式！");
        double amount = settleSimple.getPaymentMethodSet().stream().mapToDouble(SettleSimplePaymentMethod::getAmount).sum();
        if (Arith.round(Arith.sub(settleSimple.getRepletionAmount(), amount), 2) > 0.001)
            throw new RuntimeException("收款金额与实收金额不相等，请调整！");

        settleSimple.setState("approve");
        settleSimple.setApproveDate(new Date());
        settleSimple.setApproveUID(simpleRequest.getPerson());
        savaSettleItems(settleSimple);
        Set<SettleSimplePaymentMethod> paymentMethodSet = settleSimple.getPaymentMethodSet();
        if (settleSimple.getFreeAmount() > 0) {
            SettleSimplePaymentMethod settleSimplePaymentMethod = new SettleSimplePaymentMethod();
            settleSimplePaymentMethod.setPaymentMethodType(SpringManager.getBean(PaymentMethodRepository.class).getOne("112"));
            settleSimplePaymentMethod.setAmount(settleSimple.getFreeAmount());
            settleSimplePaymentMethod.setNote("免收金额！");
            paymentMethodSet.add(settleSimplePaymentMethod);
        }
        settleSimple.setPaymentMethodSet(paymentMethodSet);
        SettleSimple saveAndFlush = settleSimpleRepository.saveAndFlush(settleSimple);
        settleService.createSettleSimple(getSettleItems(saveAndFlush));//自动创建客户结算
        return saveAndFlush;
    }

    private Settle getSettleItems(SettleSimple settleSimple) {
        Settle settle = new Settle();
        settle.setPartner(settleSimple.getPartner());
        settle.setCompany(settleSimple.getCompany());
        settle.setOrigin(settleSimple.getId());
        settle.setOriginBusinessName("SettleSimple");
        settle.setDept(settleSimple.getDept());
        settle.setCooperation(settleSimple.getCooperation());
        settle.setSettleAmount(settleSimple.getSettleAmount());
        settle.setCreator(settleSimple.getCreator());
        settle.setNote("客户结算（简）自动生成！");
        List<SettleItem> settleItems = new ArrayList<>();
        settleSimple.getSettleSimpleItems().forEach(v -> {
            InvoiceItem invoiceItem = invoiceItemRepository.getOne(v.getInvoiceItem().getId());
            SettleItem settleItem = new SettleItem();
            settleItem.setCarLicense(v.getCarLicense());
            settleItem.setOriginBusinessType(v.getOriginBusinessType());
            settleItem.setOrigin(v.getOrigin());
            settleItem.setProduct(v.getProduct());
            settleItem.setUom(v.getUom());
            settleItem.setPendingQty(v.getPendingQty());
            settleItem.setActualQty(v.getActualQty());
            settleItem.setAmount(v.getAmount());
            settleItem.setOccurrenceDate(new Date());
            settleItem.setSource(v.getSource());
            settleItem.setSourceBusinessType(v.getSourceBusinessType());
            settleItem.setTax(v.getInvoiceItem().getTax());
            settleItem.setInvoiceItem(v.getInvoiceItem());
            settleItem.setDept(settleSimple.getDept());
            settleItem.setPriceUnit(v.getPriceUnit());
            settleItem.setAmtTax(invoiceItem.getAmtTax());
            settleItem.setAmtUntaxed(invoiceItem.getAmtUntaxed());
            settleItems.add(settleItem);
        });

        settle.setSettleItems(settleItems);
        settle.setSettleTax(settle.getSettleItems().stream().mapToDouble(SettleItem::getAmtTax).sum());
        return settle;
    }

    /*
     * 删除
     * */
    public String delete(SimpleRequest simpleRequest) {
        SettleSimple settleSimple = settleSimpleRepository.getOne(simpleRequest.get("id"));
        deleteSettleItems(settleSimple);

        extracted(settleSimple, "delete");
        settleSimpleRepository.delete(settleSimple.getId());
        return "删除成功！";
    }

    private void extracted(SettleSimple settleSimple, String state) {
        if (Objects.isNull(settleSimple.getCompany())) return;
        ledgerService.charge(settleSimple.getCompany(), settleSimple.getDept(), settleSimple.getPartner(),
                "IM_OWN", "AM_PURCHASE", settleSimple.getId(), settleSimple.getInnerBusinessType(),
                new Date(), "current_unsettled", "delete".equals(state) ? settleSimple.getSettleAmount() : settleSimple.getSettleAmount() * -1);
    }

    /**
     * 写入总账
     */
    private void transaction(SettleSimple settleSimple, Object... items) {
        ledgerService.transaction(settleSimple.getCompany(), settleSimple.getDept(), settleSimple.getPartner(),
                settleSimple.getCooperation().getInventoryMode(), settleSimple.getCooperation().getAccountingMethod(),
                settleSimple.getId(), settleSimple.getInnerBusinessType(), new Date(), items);
    }

    private Map findOrderInfo(SimpleRequest request) {
        JSONObject json = request.getJO();
        JSONObject param = parseCondition(json.getJSONArray("condition"));

        JSONArray all = settleSimpleDao.findDept(param, request.getPostId(), request.get("page"), request.get("size"));
        Object count = settleSimpleDao.findDeptCount(param, request.getPostId());
        JSONObject result = new JSONObject();
        result.put("content", all);
        result.put("total", ((JSONObject) ((JSONArray) count).get(0)).get("COUNT"));
        result.put("pages", ((JSONObject) ((JSONArray) count).get(0)).get("COUNT"));
        return result;
    }

    /**
     * 解析前端参数
     *
     * @param array filter 参数，解析日期格式
     * @return
     */
    public JSONObject parseCondition(JSONArray array) {
        JSONObject model = new JSONObject();
        array.forEach(v -> {
            JSONObject filter = (JSONObject) v;
            if ("GTE".equals(filter.getString("operator")) && "create_date".equals(filter.getString("field"))) {
                model.put(filter.getString("field") + "_DATE", filter.getString("value"));//因时间类型的查询条件有两个值，不好区分,所以在字段名后加_DATE
            } else if ("GTE".equals(filter.getString("operator")) && "approve_date".equals(filter.getString("field"))) {
                model.put(filter.getString("field") + "_DATE", filter.getString("value"));//因时间类型的查询条件有两个值，不好区分,所以在字段名后加_DATE
            } else {
                model.put(filter.getString("field"), filter.get("value"));
            }
        });
        return model;
    }

    private SettleSimple findOne(SimpleRequest request) {
        SettleSimple settleSimple = new SettleSimple();
        List<Map> maps = settleSimpleRepository.findByOne(request.get("id").toString());
        maps.stream().forEach(v -> {
            settleSimple.setId(v.get("ID").toString());
            settleSimple.setPartner(partyRoleRepository.getOne(v.get("PARTNER_ID").toString()));
            settleSimple.setSettleAmount(Double.parseDouble(v.get("SETTLE_AMOUNT").toString()));
            settleSimple.setCompany(partyRoleRepository.getOne(v.get("COMPANY_ID").toString()));
            settleSimple.setCooperation(SpringManager.getBean(CooperationRepository.class).getOne(v.get("COOPERATION_ID").toString()));
            settleSimple.setState(v.get("STATE") == null ? null : v.get("STATE").toString());
            settleSimple.setNote(v.get("NOTE") == null ? null : v.get("NOTE").toString());
            settleSimple.setVersion(v.get("VERSION") == null ? null : Integer.parseInt(v.get("VERSION").toString()));
            settleSimple.setCreator(v.get("CREATOR_ID") == null ? null : v.get("CREATOR_ID").toString());
            settleSimple.setInnerBusinessType(v.get("INNER_BUSINESS_TYPE") == null ? null : v.get("INNER_BUSINESS_TYPE").toString());
            settleSimple.getInnerBusinessKey();
            if (!StringUtils.isEmpty(v.get("DEPT_ID"))) {
                settleSimple.setDept(v.get("DEPT_ID") == null ? null : SpringManager.getBean(DeptRepository.class).getOne(v.get("DEPT_ID").toString()));
            }
            settleSimple.setSettleAmount(v.get("SETTLE_AMOUNT") == null ? null : Arith.round(Double.parseDouble(v.get("SETTLE_AMOUNT").toString()), 2));
            settleSimple.setFreeAmount(v.get("FREE_AMOUNT") == null ? null : Arith.round(Double.parseDouble(v.get("FREE_AMOUNT").toString()), 2));
            settleSimple.setRepletionAmount(v.get("REPLETION_AMOUNT") == null ? null : Arith.round(Double.parseDouble(v.get("REPLETION_AMOUNT").toString()), 2));
            settleSimple.setNote(v.get("NOTE") == null ? null : v.get("NOTE").toString());
        });

        Set<SettleSimpleItem> settleSimpleItems = new HashSet<>();
        JSONArray jsonArray = settleSimpleDao.findSettleSimpleItem(request.get("id").toString());
        jsonArray.stream().forEach(v -> {
            JSONObject json = (JSONObject) v;
            SettleSimpleItem settleSimpleItem = new SettleSimpleItem();
            settleSimpleItem.setCarLicense(json.getString("CAR_LICENSE"));
            settleSimpleItem.setOriginBusinessType(json.getString("ORIGIN_BUSINESS_TYPE"));
            settleSimpleItem.setOrigin(json.getString("ORIGIN"));
            settleSimpleItem.setAmount(json.getDoubleValue("AMOUNT"));
            settleSimpleItem.setFreeAmount(json.getDoubleValue("FREE_AMOUNT"));
            settleSimpleItem.setRepletionAmount(json.getDoubleValue("REPLETION_AMOUNT"));
            settleSimpleItem.setActualQty(json.getDoubleValue("ACTUAL_QTY"));
            settleSimpleItem.setPendingQty(json.getDoubleValue("PENDING_QTY"));
            settleSimpleItem.setOccurrenceDate(json.getDate("OCCURRENCE_DATE"));
            settleSimpleItem.setSource(json.getString("SOURCE"));
            settleSimpleItem.setInvoiceItem(invoiceItemRepository.findOne(json.getLong("INVOICE_ID")));
            settleSimpleItem.setSourceBusinessType(json.getString("SOURCE_BUSINESS_TYPE"));
            settleSimpleItem.setNote(json.getString("NOTE"));

            //商品
            Product product = new Product();
            product.setId(json.getString("PRODUCT_ID"));
            product.setName(json.getString("PRODUCT_NAME"));
            settleSimpleItem.setProduct(product);

            //计量单位
            ProductUom productUom = new ProductUom();
            productUom.setId(Long.valueOf(json.getString("PRODUCT_UOM_ID")));
            productUom.setName(json.getString("PRODUCT_UOM_NAME"));
            settleSimpleItem.setUom(productUom);
            settleSimpleItems.add(settleSimpleItem);
        });
        settleSimple.setSettleSimpleItems(settleSimpleItems);

        JSONArray paymentMethod = settleSimpleDao.findSettleSimplePaymentMethod(request.get("id").toString());
        Set<SettleSimplePaymentMethod> paymentMethodSet = new HashSet();
        paymentMethod.stream().forEach(v -> {
            JSONObject json = (JSONObject) v;
            SettleSimplePaymentMethod settleSimplePaymentMethod = new SettleSimplePaymentMethod();
            settleSimplePaymentMethod.setPaymentMethodType(SpringManager.getBean(PaymentMethodRepository.class).getOne(json.getString("PAYMENT_METHOD_TYPE")));
            settleSimplePaymentMethod.setAmount(json.getDoubleValue("AMOUNT"));
            settleSimplePaymentMethod.setNote(json.getString("NOTE"));
            if (!StringUtils.isEmpty(json.getString("BANK_ACCOUNT_ID"))) {
                BankAccount methodType = SpringManager.getBean(BankAccountRepository.class).getOne(json.getString("BANK_ACCOUNT_ID"));
                settleSimplePaymentMethod.setBankAccount(methodType);
                settleSimplePaymentMethod.setBankAccountId(methodType.getAccountId());
            }
            paymentMethodSet.add(settleSimplePaymentMethod);
        });
        settleSimple.setPaymentMethodSet(paymentMethodSet);
        return settleSimple;
    }

    /*
     * 结算单申请开票
     * */
    public Map applyInvoice(SimpleRequest simpleRequest) {
        JSONObject info = simpleRequest.getJO().getJSONObject("info");
        SettleSimple settleSimple = settleSimpleRepository.findOne(info.getString("id"));
        settleSimple.setInvoiceState("finish");
        // 生成发票申请明细
        List<Map> item = new ArrayList<>();
        settleSimple.getSettleSimpleItems().forEach(settleItem -> {
            Product product = settleItem.getProduct();
            item.add(MapUtil.mapper(
                    "origin", settleSimple.getId(),
                    "itemId", settleItem.getId(),
                    "sourceBusinessTypeName", settleItem.getOriginBusinessType(),
                    "originBusinessTypeName", "客户结算",
                    "source", settleItem.getOrigin(),
                    "sourceItemId", settleItem.getId(),
                    "carLicense", settleItem.getCarLicense(),
                    "actualInvoicedAmount", settleItem.getRepletionAmount(),
                    "priceTotal", settleItem.getRepletionAmount(),
                    "productQty", settleItem.getActualQty(),
                    "product", MapUtil.mapped(product),
                    "uom", MapUtil.mapped(settleItem.getUom()),
                    "specifications", product.getSpecifications(),
                    "model", product.getModel(),
                    "serveType", MapUtil.mapped(product.getServeType()),
                    "productGroup", MapUtil.mapped(product.getProductGroup())

            ));
        });

        //创建发票申请单-直营
        Object invoiceApply = invoke("direct.invoiceApply.create",
                MapUtil.mapper(
                        "saleCategory", "settle",
                        "invoiceCompany", MapUtil.mapped(settleSimple.getCompany()),
                        "company", MapUtil.mapped(settleSimple.getCompany()),
                        "invoiceType", MapUtil.mapped(info.get("invoiceType")),
                        "buyerName", info.getString("buyerName"),
                        "buyerInfo", info.getString("buyerInfo"),
                        "buyerTaxNumber", info.getString("buyerTaxNumber"),
                        "buyerBankInfo", info.getString("buyerBankInfo"),
                        "email", info.getString("email"),
                        "totalSaleAmount", settleSimple.getRepletionAmount(),
                        "invoicedAmount", settleSimple.getRepletionAmount(),
                        "actualInvoicedAmount", settleSimple.getRepletionAmount(),
                        "invoiceApplyItems", item
                ));
        invoiceApply = invoke("direct.invoiceApply.apply", invoiceApply);
        Map map = MapUtil.mapped(invoiceApply);
        Map settleMap = MapUtil.mapped(settleSimpleRepository.findOne(settleSimple.getId()));
        settleMap.put("invoiceApplyId", map.get("id"));
        List<Settle> settleList = settleRepository.findAll(JpaDsl.toCriteriaByEq("origin", settleSimple.getId()));
        Settle settle = settleRepository.findOne(settleList.get(0).getId());
        settle.setInvoiceState("finish");
        settleRepository.saveAndFlush(settle);
        return settleMap;
    }

    /**
     * 客户应收报表查询
     * @param simpleRequest
     * @return
     * @throws Exception
     */
    public JSONObject accountsReceivable(SimpleRequest simpleRequest) throws Exception {
        JSONObject json = simpleRequest.getJO();

        JSONObject param = parseCondition(json.getJSONArray("condition"));
        List<Map> all = new ArrayList<>();
        Object count = new JSONObject();
        if ("1".equals(param.get("BELONG").toString())) {
            String create_date_date = param.getString("create_date_DATE").substring(0, 7);
            param.put("create_date_date1",create_date_date);
            all = settleSimpleDao.accountsReceivable(param, simpleRequest.getPostId(), simpleRequest.get("page"), simpleRequest.get("size"));
            count = settleSimpleDao.accountsReceivableCount(param, simpleRequest.getPostId());
        } else if ("2".equals(param.get("BELONG").toString())) {
            String create_date_date = param.getString("create_date_DATE").substring(0, 4);
            param.put("create_date_date1",create_date_date);
            all = settleSimpleDao.accountsReceivableSummary(param, simpleRequest.getPostId(), simpleRequest.get("page"), simpleRequest.get("size"));
            count = settleSimpleDao.accountsReceivableSummaryCount(param, simpleRequest.getPostId());
        }
        all.stream().forEach(v -> {
            String CONCAT_DATE = v.get("CREATE_DATE").equals(param.get("create_date_DATE").toString().substring(0, 7))
                    ? param.get("create_date_DATE").toString() :  v.get("CURRENT_DATE").toString();
            Object ledger = settleSimpleDao.findLedger(v.get("COMPANY_ID").toString(), v.get("PARTNER_ID").toString(), CONCAT_DATE);
            partyRoleRepository.findOne(v.get("COMPANY_ID").toString());
            v.put("CONCAT_DATE", CONCAT_DATE);
            String MAX_DATA = v.get("CREATE_DATE").equals(param.get("create_date").toString().substring(0, 7))
                    ? param.get("create_date").toString() :  v.get("MAX_DATA").toString();
            v.put("MAX_DATA", MAX_DATA);
            v.put("COMPANY_NAME", partyRoleRepository.findOne(v.get("COMPANY_ID").toString()).getName());
            v.put("PARTNER_NAME", partyRoleRepository.findOne(v.get("PARTNER_ID").toString()).getName());
            v.put("PRICE_SUBTOTAL", (StringUtils.isEmpty(v.get("PRICE_SUBTOTAL"))||"".equals(v.get("PRICE_SUBTOTAL")) ? 0 : Double.valueOf(v.get("PRICE_SUBTOTAL").toString())));
            v.put("FREE_AMOUNT", (StringUtils.isEmpty(v.get("FREE_AMOUNT")) || "".equals(v.get("FREE_AMOUNT")) ? 0 : Double.valueOf(v.get("FREE_AMOUNT").toString())));
            v.put("RECEIPTS_AMOUNT", (StringUtils.isEmpty(v.get("RECEIPTS_AMOUNT")) || "".equals(v.get("RECEIPTS_AMOUNT")) ? 0 : Double.valueOf(v.get("RECEIPTS_AMOUNTs").toString())));
            v.put("SETTLE_AMOUNT", (StringUtils.isEmpty(v.get("SETTLE_AMOUNT")) || "".equals(v.get("SETTLE_AMOUNT")) ? 0 : Double.valueOf(v.get("SETTLE_AMOUNT").toString())));
            v.put("AMOUNT", ((JSONArray) ledger).size() < 1 ? 0 : ((JSONObject) ((JSONArray) ledger).get(0)).get("AMOUNT"));
            Double endingBalance = ((JSONArray) ledger).size() < 1 ? 0 : Double.valueOf(((JSONObject) ((JSONArray) ledger).get(0)).get("AMOUNT").toString())
                    + (StringUtils.isEmpty(v.get("PRICE_SUBTOTAL"))||"".equals(v.get("PRICE_SUBTOTAL")) ? 0 : Double.valueOf(v.get("PRICE_SUBTOTAL").toString()))
                    - (StringUtils.isEmpty(v.get("SETTLE_AMOUNT")) || "".equals(v.get("SETTLE_AMOUNT")) ? 0 : Double.valueOf(v.get("SETTLE_AMOUNT").toString()));
            v.put("ENDING_BALANCE", endingBalance);
        });

        JSONObject result = new JSONObject();
        result.put("content", all);
        result.put("total", ((JSONObject) ((JSONArray) count).get(0)).get("COUNT"));
        result.put("pages", ((JSONObject) ((JSONArray) count).get(0)).get("COUNT"));
        result.put("footer", Arrays.asList(MapUtil.mapper(
                "AMOUNT", all.stream().map(x -> Double.valueOf(x.get("AMOUNT").toString())).reduce(Arith::add).orElse(0.0),
                "PRICE_SUBTOTAL", all.stream().map(x -> Double.valueOf(x.get("PRICE_SUBTOTAL").toString())).reduce(Arith::add).orElse(0.0),
                "SETTLE_AMOUNT", all.stream().map(x -> Double.valueOf(x.get("SETTLE_AMOUNT").toString())).reduce(Arith::add).orElse(0.0),
                "FREE_AMOUNT", all.stream().map(x -> Double.valueOf(x.get("FREE_AMOUNT").toString())).reduce(Arith::add).orElse(0.0),
                "RECEIPTS_AMOUNT", all.stream().map(x -> Double.valueOf(x.get("RECEIPTS_AMOUNT").toString())).reduce(Arith::add).orElse(0.0),
                "ENDING_BALANCE", all.stream().map(x -> Double.valueOf(x.get("ENDING_BALANCE").toString())).reduce(Arith::add).orElse(0.0)
        )));
        return result;
    }

}
